﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Sustainalytics.Auth.Claims;
using Sustainalytics.ClientDW.Entities.Universes;
using Sustainalytics.Universes.BusinessLogic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Sustainalytics.Universes.Service.Tests
{
    [TestClass]
    public class UniversesBusinessLogicTests
    {
        [TestMethod]
        public void UploadFile()
        {
            var expectedId = Guid.NewGuid();
            var expectedName = "universe_upload.xlsx";
            var expectedtype = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

            var inputStream = new MemoryStream(File.ReadAllBytes(@"./Resources/universe_upload.xlsx"));
            var insertedName = string.Empty;
            var insertedtype = string.Empty;
            var insertedid = Guid.Empty;
            var arrByte = new byte[inputStream.Length];
            inputStream.Read(arrByte, 0, arrByte.Length);
            var insertedMS = new MemoryStream(arrByte);

            var rep = new ClientDW.DataAccessLayer.Fakes.StubIUniversesRepository
            {
                UploadFileGuidStringString = (id, name, type) =>
                {
                    insertedName = name;
                    insertedtype = type;
                    insertedid = id;
                    return new Tuple<Stream, Guid>(insertedMS, id);
                }
            };

            var management = Universes.BusinessLogic.UniversesManagement.GetInstance(rep);
            var response = management.UploadFile(expectedId, expectedName, expectedtype);

            Assert.IsNotNull(response, "The response is null.");
            Assert.AreEqual(expectedId, insertedid, "The id is different than the expected one.");
            Assert.AreEqual(insertedName, expectedName, "The filename is different than the expected one.");
            Assert.AreEqual(insertedtype, expectedtype, "The content type is different than the expected one.");
            Assert.IsTrue(UniversesControllerTests.StreamsAreIdentical(inputStream, response.Item1), "The response stream is different than the expected one.");
        }

        [TestMethod]
        public void IsProcessingScheduled()
        {
            var rep = new ClientDW.DataAccessLayer.Fakes.StubIUniversesRepository
            {
                IsProcessingScheduled = () => true
            };

            var management = Universes.BusinessLogic.UniversesManagement.GetInstance(rep);
            var isProcessing = management.IsProcessingScheduled();
            Assert.IsTrue(isProcessing, "The current state of processing is different than expected.");
        }

        [TestMethod]
        public void AddUploadLogs()
        {
            UploadLog savedLog = null;
            var insertedLog = new UploadLog
            {
                Id = Guid.NewGuid(),
                Processed = true,
                Created = DateTime.UtcNow,
                UserId = Guid.Empty,
                FileId = Guid.NewGuid(),
                UploadType = UploadType.UniversesUpload
            };

            var rep = new ClientDW.DataAccessLayer.Fakes.StubIUniversesRepository
            {
                AddUploadLogsUploadLog = (log) =>
                {
                    savedLog = log;
                }
            };

            var management = Universes.BusinessLogic.UniversesManagement.GetInstance(rep);
            management.AddUploadLogs(insertedLog);

            Assert.IsNotNull(savedLog, "The saved log is null.");
            Assert.AreEqual(insertedLog.FileId, savedLog.FileId, "The saved log has a different id than expected.");
            Assert.IsTrue(savedLog.Processed, "The value of processed is different than the expected one.");
        }

        [TestMethod]
        public void GetFeatureUniveseClaims()
        {
            var accountId = Guid.NewGuid();
            var featureUniverses = new List<FeatureUniverse>();
            featureUniverses.Add(new FeatureUniverse { AccountId = accountId, Feature = AccountFeature.CompanySearch, UniverseIds = new List<int> { 1, 4, 6, 3 } });
            featureUniverses.Add(new FeatureUniverse { AccountId = accountId, Feature = AccountFeature.GlobalCompactWatchlistAndNonCompliant, UniverseIds = new List<int> { 6, 3 } });
            featureUniverses.Add(new FeatureUniverse { AccountId = accountId, Feature = AccountFeature.ScreeningToolEnvironment, UniverseIds = new List<int> { 7, 2, 5 } });
            featureUniverses.Add(new FeatureUniverse { AccountId = Guid.NewGuid(), Feature = AccountFeature.CompanySearch, UniverseIds = new List<int> { 1, 4, 2, 5 } });

            var rep = new ClientDW.DataAccessLayer.Fakes.StubIUniversesRepository
            {
                GetFeatureUniveseByAccountIdGuid = (accId) => featureUniverses.Where(fu => fu.AccountId == accId).ToList()
            };

            var management = UniversesManagement.GetInstance(rep);

            var claims = management.GetFeatureUniveseClaims(accountId);

            Assert.IsNotNull(claims, "The list of claims should not be null.");
            Assert.AreEqual(3, claims.Count, "The number of claims is different than the expected one.");
        }
    }
}
